package myJs.implicits

import myJs.Implicits._

trait MyListTool {

  implicit class MyList[T](list: List[T]) {

    def optionMap = {
      list.map { x =>
        (x -> x)
      }.toSeqMap
    }

    def containsAll(elems: List[T]) = {
      elems.forall(x => list.contains(x))
    }

    def containsAny(elems: List[T]) = {
      elems.exists(x => list.contains(x))
    }

    def distinctBy[B](f: T => B) = {
      list.map { x =>
        (f(x), x)
      }.toMap.values.toList
    }

    def distinctByKeepHead[B](f: T => B): List[T] = {

      def loop(list: List[T], acc: (List[T], Set[B])): (List[T], Set[B]) = {
        list match {
          case Nil => acc
          case x :: xs =>
            val key = f(x)
            val (list, set) = acc
            if (!set.contains(key)) {
              loop(xs, (list ::: List(x), set + (key)))
            } else loop(xs, acc)
        }
      }

      loop(list, (List[T](), Set[B]()))._1
    }

    def removedByI(i: Int) = {
      list.zipWithIndex.filterNot { case (v, curI) =>
        curI == i
      }.map(_._1)
    }

    def removed(e: T) = {
      list.filterNot { v =>
        v == e
      }
    }

    def get(i: Int) = {
      if (list.isDefinedAt(i)) {
        Some(list(i))
      } else None
    }

    def removeAll(rl: List[T]) = {
      list.filterNot { v =>
        rl.contains(v)
      }
    }

    def removedV(e: T) = {
      list.filterNot { v =>
        v == e
      }
    }

    def insert(i: Int, default: T) = {
      list.take(i) ::: List(default) ::: list.drop(i)
    }

    def getOrElse(i: Int, default: T) = {
      if (list.isDefinedAt(i)) {
        list(i)
      } else default
    }

  }

  implicit class MyListStr(list: List[String]) {

    def containsIgnoreCase(key: String) = {
      list.map { x =>
        x.toLowerCase
      }.contains(key.toLowerCase)
    }

  }


}
